package com.ruoyi.gateway.filter;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.CollectionUtils;
import org.springframework.util.PathMatcher;
import org.springframework.web.server.ServerWebExchange;

import com.ruoyi.common.core.utils.ServletUtils;
import com.ruoyi.gateway.config.properties.RefererProperty;

import reactor.core.publisher.Mono;

/**
 * @author Hey, rog
 * @version V1.0
 * @since 2023/1/11 15:12
 */
@Component
public class RefererFilter implements GlobalFilter, Ordered {

    private static final Logger log = LoggerFactory.getLogger(AuthFilter.class);
	
	@Autowired
    private RefererProperty refererProperty;

    private static PathMatcher pathMatcher = new AntPathMatcher();

    /**
     * 是否存在支持跨站点配置地址，存在true、不存在false
     */
    private boolean existsReferer(ServerHttpRequest request) {
        String referer = request.getHeaders().getFirst(HttpHeaders.REFERER);
        log.debug("当前请求路径: {}", request.getURI());
        log.debug("当前referer: {}", referer);
        if (null == referer || "".equals(referer)) {
            return false;
        }
        List<String> allows = this.refererProperty.getExcludes();
        if (null!= allows && !CollectionUtils.isEmpty(allows)) {
            return allows.stream().anyMatch(url -> {
            	return referer.contains(url);
            });
        }
        return false;
    }

    /**
     * 是否存在白名单
     */
    @SuppressWarnings("unused")
	private boolean isBlank(ServerHttpRequest request) {
        String path = request.getPath().value();
        List<String> excludes = refererProperty.getIncludes();
        for (String exclude : excludes) {
            if (pathMatcher.match(exclude, path)) {
                return true;
            }
        }
        return false;
    }

	@Override
	public int getOrder() {
		return -200;
	}

	@Override
	public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
		ServerHttpRequest request = exchange.getRequest();
		ServerHttpRequest.Builder mutate = request.mutate();

		// 检测地址是否在白名单，若在直接放过
//		if (isBlank(request)) {
//			return chain.filter(exchange.mutate().request(mutate.build()).build());
//		}

		System.out.println("referer = " + request.getHeaders().getFirst(HttpHeaders.REFERER));
		
		// 启用了Refer检测且不存在配置站点直接拦截
		if (null != refererProperty.getEnabled() && refererProperty.getEnabled() && !existsReferer(request)) {
			return ServletUtils.webFluxResponseWriter(exchange.getResponse(), HttpStatus.BAD_REQUEST, "非法访问", 400);
		}
		return chain.filter(exchange.mutate().request(mutate.build()).build());
	}
}